#ifndef DISK_CACHE_H
#define DISK_CACHE_H

#include "lru_cache.h"
#include <fstream>
#include <filesystem>
#include <sstream>
#include <iomanip>
#include <cstring>
#include <chrono>

// 磁盘缓存层（L2缓存）
// 继承自LRU缓存，将数据持久化到磁盘
template<typename KeyType, typename ValueType>
class DiskCache : public LRUCache<KeyType, ValueType> {
private:
    std::string cache_directory_;                                  // 缓存目录路径
    size_t max_disk_size_;                                         // 最大磁盘使用量（字节）
    size_t current_disk_usage_;                                    // 当前磁盘使用量（字节）

    // 序列化和反序列化函数
    using Serializer = std::function<std::string(const ValueType&)>;
    using Deserializer = std::function<ValueType(const std::string&)>;

    Serializer serializer_;
    Deserializer deserializer_;

    // 将键转换为文件名
    std::string keyToFilename(const KeyType& key) const {
        std::stringstream ss;
        ss << std::hash<KeyType>{}(key);
        return cache_directory_ + "/" + ss.str() + ".cache";
    }

    // 获取文件大小
    size_t getFileSize(const std::string& filename) const {
        if (std::filesystem::exists(filename)) {
            return std::filesystem::file_size(filename);
        }
        return 0;
    }

    // 写入数据到磁盘
    bool writeToDisk(const KeyType& key, const ValueType& value) {
        std::string filename = keyToFilename(key);
        std::string data = serializer_ ? serializer_(value) : defaultSerializer(value);

        std::ofstream file(filename, std::ios::binary);
        if (!file) {
            return false;
        }

        file.write(data.c_str(), data.size());
        file.close();

        current_disk_usage_ += data.size();
        return true;
    }

    // 从磁盘读取数据
    bool readFromDisk(const KeyType& key, ValueType& value) {
        std::string filename = keyToFilename(key);
        if (!std::filesystem::exists(filename)) {
            return false;
        }

        std::ifstream file(filename, std::ios::binary);
        if (!file) {
            return false;
        }

        std::string data((std::istreambuf_iterator<char>(file)),
                        std::istreambuf_iterator<char>());
        file.close();

        value = deserializer_ ? deserializer_(data) : defaultDeserializer(data);
        return true;
    }

    // 从磁盘删除数据
    void removeFromDisk(const KeyType& key) {
        std::string filename = keyToFilename(key);
        if (std::filesystem::exists(filename)) {
            size_t file_size = getFileSize(filename);
            std::filesystem::remove(filename);
            current_disk_usage_ -= file_size;
        }
    }

    // 默认序列化器（简单的二进制写入）
    std::string defaultSerializer(const ValueType& value) const {
        return std::string(reinterpret_cast<const char*>(&value), sizeof(ValueType));
    }

    // 默认反序列化器（简单的二进制读取）
    ValueType defaultDeserializer(const std::string& data) const {
        ValueType value;
        std::memcpy(&value, data.c_str(), std::min(data.size(), sizeof(ValueType)));
        return value;
    }

protected:
    // 重写淘汰时的钩子函数
    virtual void onEvict(const KeyType& key, const ValueType& value) override {
        // 从磁盘删除对应的文件
        removeFromDisk(key);
    }

public:
    // 构造函数
    DiskCache(size_t capacity, const std::string& cache_dir, size_t max_disk_mb = 1024)
        : LRUCache<KeyType, ValueType>(capacity)
        , cache_directory_(cache_dir)
        , max_disk_size_(max_disk_mb * 1024 * 1024)
        , current_disk_usage_(0) {

        // 创建缓存目录
        if (!std::filesystem::exists(cache_directory_)) {
            std::filesystem::create_directories(cache_directory_);
        }

        // 计算现有缓存文件的总大小
        for (const auto& entry : std::filesystem::directory_iterator(cache_directory_)) {
            if (entry.is_regular_file() && entry.path().extension() == ".cache") {
                current_disk_usage_ += entry.file_size();
            }
        }
    }

    // 析构函数
    virtual ~DiskCache() {
        // 可选：清理缓存目录
        // clear();
    }

    // 设置序列化器
    void setSerializer(const Serializer& serializer) {
        serializer_ = serializer;
    }

    // 设置反序列化器
    void setDeserializer(const Deserializer& deserializer) {
        deserializer_ = deserializer;
    }

    // 重写put函数以同时写入磁盘
    virtual void put(const KeyType& key, const ValueType& value) override {
        // 检查磁盘空间限制
        std::string data = serializer_ ? serializer_(value) : defaultSerializer(value);
        if (current_disk_usage_ + data.size() > max_disk_size_) {
            // 需要淘汰一些条目以腾出空间
            while (current_disk_usage_ + data.size() > max_disk_size_ && this->size() > 0) {
                this->evict();
            }
        }

        // 写入磁盘
        if (writeToDisk(key, value)) {
            // 更新内存缓存
            LRUCache<KeyType, ValueType>::put(key, value);
        }
    }

    // 重写get函数以支持从磁盘加载
    virtual bool get(const KeyType& key, ValueType& value) override {
        // 首先尝试从内存缓存获取
        if (LRUCache<KeyType, ValueType>::get(key, value)) {
            return true;
        }

        // 如果内存中没有，尝试从磁盘加载
        if (readFromDisk(key, value)) {
            // 将数据加载到内存缓存
            LRUCache<KeyType, ValueType>::put(key, value);
            return true;
        }

        return false;
    }

    // 重写remove函数以同时从磁盘删除
    virtual void remove(const KeyType& key) override {
        removeFromDisk(key);
        LRUCache<KeyType, ValueType>::remove(key);
    }

    // 重写clear函数以清理磁盘
    virtual void clear() override {
        // 清理所有缓存文件
        for (const auto& entry : std::filesystem::directory_iterator(cache_directory_)) {
            if (entry.is_regular_file() && entry.path().extension() == ".cache") {
                std::filesystem::remove(entry.path());
            }
        }
        current_disk_usage_ = 0;
        LRUCache<KeyType, ValueType>::clear();
    }

    // 获取当前磁盘使用量
    size_t getCurrentDiskUsage() const {
        return current_disk_usage_;
    }

    // 获取最大磁盘限制
    size_t getMaxDiskSize() const {
        return max_disk_size_;
    }

    // 获取磁盘使用率
    double getDiskUsageRatio() const {
        if (max_disk_size_ == 0) return 0.0;
        return static_cast<double>(current_disk_usage_) / max_disk_size_;
    }

    // 打印缓存统计信息
    void printStatistics() const {
        std::cout << "\n=== 磁盘缓存（L2）统计信息 ===" << std::endl;
        std::cout << "缓存目录: " << cache_directory_ << std::endl;
        std::cout << "缓存容量: " << this->capacity() << " 条" << std::endl;
        std::cout << "当前大小: " << this->size() << " 条" << std::endl;
        std::cout << "磁盘使用: " << current_disk_usage_ / (1024.0 * 1024.0)
                  << " MB / " << max_disk_size_ / (1024.0 * 1024.0) << " MB" << std::endl;
        std::cout << "磁盘使用率: " << (getDiskUsageRatio() * 100) << "%" << std::endl;
        std::cout << "命中次数: " << this->getHitCount() << std::endl;
        std::cout << "未命中次数: " << this->getMissCount() << std::endl;
        std::cout << "命中率: " << (this->getHitRate() * 100) << "%" << std::endl;
        std::cout << "==============================\n" << std::endl;
    }

    // 同步内存缓存到磁盘（可用于定期持久化）
    void sync() {
        // 这个方法可以用于强制将内存中的所有数据写入磁盘
        // 在当前实现中，数据已经在put时写入磁盘，所以这里可以留空
        // 或者实现批量写入优化
    }
};

#endif // DISK_CACHE_H